// // #include "dsgn_preprocess.h"
#include <iostream>
#include <fstream>
// #include <vector>
#include <cuda.h>
#include <stdio.h>
#include <cuda_runtime.h>
#include <opencv2/opencv.hpp>
#include "NvInfer.h"
#include "NvOnnxConfig.h"
#include "NvOnnxParser.h"
#include "NvInferRuntime.h"
// #include "DpsCostVolume_kernel.hpp"


// // template <typename T>
// // __global__ void RandomCropandPad_kernel(T* input, T* output, 
// //                         int inputwidth, int inputheight, int outputwidth, int outputheight, 
// //                         int start_x, int start_y, int channels)
// // {
// //     int x = blockIdx.x * blockDim.x * threadIdx.x;
// //     int y = blockIdx.y * blockDim.y * threadIdx.y;
// //     // int c = blockIdx.z * blockDim.z * threadIdx.z;
// //     int padded_height, padded_width;

// //     if (outputheight > inputheight){
// //         padded_height = int (outputheight - inputheight) / 2;
// //     }else{
// //         padded_height = 0;
// //     }
// //     if (outputwidth > inputwidth){
// //         padded_width = int (outputwidth - inputwidth) / 2;
// //     }else{
// //         padded_width = 0;
// //     }
// //     int inputIndex = ;
// //     int outputIndex = (y + padded_height - start_y) * outputwidth * channels + (x + padded_width - start_x) * channels + c;
// //     if (x >= start_x - padded_width && x <= inputwidth && y >= start_y - padded_height && y <= inputheight){
// //         output[outputIndex] = input[inputIndex];
// //     }else{
// //         output[outputIndex] = 0;
// //     }
// // }


// template <typename T>
// __global__ void RandomCrop_kernel(T* input, T* output, 
//                         int inputwidth, int inputheight, int outputwidth, int outputheight, 
//                         int start_x, int start_y, int channels)
// {
//     int x = blockIdx.x * blockDim.x + threadIdx.x;
//     int y = blockIdx.y * blockDim.y + threadIdx.y;
//     // int c = blockIdx.z;
//     int outputIndex = y * outputwidth * channels + x * channels ;
//     int inputIndex = (y + start_y) * inputwidth * channels + (x + start_x) * channels;
//     if (x <= outputwidth && y <= outputheight){
//         output[outputIndex] = input[inputIndex];
//         output[outputIndex + 1] = input[inputIndex + 1];
//         output[outputIndex + 2] = input[inputIndex + 2];
//     }
// }



// // template <typename T>
// cudaError_t RandomCrop_launch(unsigned char* input, unsigned char* output,
//                         int inputwidth, int inputheight, int outputheight, int outputwidth, 
//                         int start_x, int start_y, int channels,
//                         cudaStream_t stream)
// {

//     // int threadNum = THREADS_FOR_VOXEL;
//     const dim3 block_size(10, 10);
//     const dim3 grid_size((outputwidth + block_size.x - 1) / block_size.x, (outputheight + block_size.y - 1) / block_size.y);
//     std::cout << "block_size " << block_size.x << " " << block_size.y << std::endl;
//     std::cout << "grid_size " << grid_size.x << " " << grid_size.y  << std::endl;
//     RandomCrop_kernel<<<grid_size, block_size>>>(input, output, 
//                                     inputwidth, inputheight, outputwidth, outputheight, start_x, start_y, channels);
//     cudaError_t err = cudaGetLastError();
//     return err;
// }


template <typename T>
__global__ void generate_downsampled_depth_kernel(T* output, const int maxdisp, const int downsample_disp, 
                         const float downsampled_depth_offset, const float depth_interval, const float min_depth, cudaError_t stream){
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    output[x] = (x + downsampled_depth_offset) * downsample_disp * depth_interval + min_depth;

}


template <typename T>
__global__ void prepare_coordinates_psv(const float point_cloud_range, const float voxel_size, const int sample_rate, cudaStream_t stream)